package com.zzyl.service.impl;


import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.json.JSONUtil;
import com.aliyun.iot20180120.Client;
import com.aliyun.iot20180120.models.*;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.zzyl.base.PageResponse;
import com.zzyl.config.AliIoTConfigProperties;
import com.zzyl.dto.DeviceDto;
import com.zzyl.dto.DevicePageQueryDto;
import com.zzyl.entity.Device;
import com.zzyl.enums.BasicEnum;
import com.zzyl.exception.BaseException;
import com.zzyl.mapper.DeviceMapper;
import com.zzyl.service.DeviceService;
import com.zzyl.vo.DeviceDataGraphVo;
import com.zzyl.vo.DeviceVo;
import com.zzyl.vo.ProductVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.support.collections.DefaultRedisList;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @version 1.0
 * @Author 小王要变胖
 * @Date 2025/2/10 17:25
 * @注释
 */
@Service
public class DeviceServiceImpl implements DeviceService {
    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Autowired
    private Client client;

    @Autowired
    private AliIoTConfigProperties aliIoTConfigProperties;

    @Autowired
    private DeviceMapper deviceMapper;

    @Override
    public void syncProductList() {

        QueryProductListRequest request = new QueryProductListRequest();
        request.setCurrentPage(1);
        request.setPageSize(100);
        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        QueryProductListResponse queryProductListResponse = null;
        try {
            queryProductListResponse = client.queryProductList(request);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

        // 如果获取成功，则保存数据
        if (queryProductListResponse.getBody().success) {
            List<QueryProductListResponseBody.QueryProductListResponseBodyDataListProductInfo>
                    productInfo = queryProductListResponse.getBody().getData().getList().getProductInfo();
            redisTemplate.opsForValue().set("device:productList", JSONUtil.toJsonStr(productInfo));
        }
    }

    @Override
    public List<ProductVo> allProduct() {
        String s = redisTemplate.opsForValue().get("device:productList");
        List<ProductVo> list = JSONUtil.toList(s, ProductVo.class);
        return list;
    }

    // 注册设备
    @Override
    public void registerDevice(DeviceDto deviceDto) {
        // 查询设备名称是否重复
        int count = deviceMapper.queryNickName(deviceDto.getNickname());
        if (count > 0) {
            // 设备名称重复
            throw new BaseException(BasicEnum.DEVICE_NAME_EXIST);
        }

        // IOT新增设备
        RegisterDeviceRequest request = new RegisterDeviceRequest();
        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        request.setDeviceName(deviceDto.getDeviceName());
        request.setNickname(deviceDto.getNickname());
        request.setProductKey(deviceDto.getProductKey());

        RegisterDeviceResponse registerDeviceResponse = null;
        try {
            registerDeviceResponse = client.registerDevice(request);
        } catch (Exception e) {
            throw new BaseException(BasicEnum.IOT_REGISTER_DEVICE_ERROR);
        }
        // 如果IOT返回数据异常，报错
        if (!registerDeviceResponse.getBody().success) {
            throw new BaseException(BasicEnum.IOT_REGISTER_DEVICE_ERROR);
        }

        // 查询产品key 去IOT查询产品名称，设置产品名称到IOT对象
        QueryProductRequest productRequest = new QueryProductRequest();
        productRequest.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        productRequest.setProductKey(deviceDto.getProductKey());
        QueryProductResponse queryProductResponse = null;
        try {
            queryProductResponse = client.queryProduct(productRequest);
        } catch (Exception e) {
            throw new BaseException(BasicEnum.IOT_QUERY_PRODUCT_ERROR);
        }
        // 查询产品名称失败，报异常
        if (!queryProductResponse.getBody().success) {
            throw new BaseException(BasicEnum.IOT_REGISTER_DEVICE_ERROR);
        }

        // 设置产品名称到entry实体类中
        Device device = BeanUtil.toBean(deviceDto, Device.class);
        device.setProductName(queryProductResponse.body.data.productName);
        device.setIotId(registerDeviceResponse.body.data.iotId);


        // 如果是随身设备，将绑定位置设置成-1
        if (device.getLocationType().equals(0)) {
            device.setPhysicalLocationType(-1);
        }

        // 把数据存储到数据库中
        try {
            device.setHaveEntranceGuard(0);
            deviceMapper.addProduct(device);
        } catch (Exception e) {
            // 如果数据库中新增设备失败，则删除IOT中刚刚已经新增的设备
            DeleteProductRequest deleteProductRequest = new DeleteProductRequest();
            deleteProductRequest.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
            deleteProductRequest.setProductKey(device.getProductKey());
            DeleteProductResponse deleteProductResponse = null;
            try {
                deleteProductResponse = client.deleteProduct(deleteProductRequest);
            } catch (Exception ex) {
                throw new BaseException(BasicEnum.IOT_DELETE_DEVICE_ERROR);
            }

            if(!deleteProductResponse.body.success){
                throw new BaseException(BasicEnum.IOT_REGISTER_DEVICE_ERROR);
            }
        }


    }

    @Override
    public PageResponse<DeviceVo> pageQueryDevice(DevicePageQueryDto devicePageQueryDto) {
        PageHelper.startPage(devicePageQueryDto.getPageNum(),devicePageQueryDto.getPageSize());
        Page<List<DeviceVo>> list =  deviceMapper.pageQueryDevice(devicePageQueryDto);
        return PageResponse.of(list,DeviceVo.class);
    }

    @Override
    public DeviceVo queryDeviceDetail(DeviceDto deviceDto) {
        // 根据产品和设备查询详情，去IOT查询
        QueryDeviceDetailRequest queryDeviceDetailRequest = new QueryDeviceDetailRequest();
        queryDeviceDetailRequest.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        queryDeviceDetailRequest.setProductKey(deviceDto.getProductKey());
        queryDeviceDetailRequest.setIotId(deviceDto.getIotId());
        QueryDeviceDetailResponse queryDeviceDetailResponse = null;
        try {
            queryDeviceDetailResponse = client.queryDeviceDetail(queryDeviceDetailRequest);
        } catch (Exception e) {
            throw new BaseException(BasicEnum.IOT_QUERY_DEVICE_ERROR);
        }
        if(!queryDeviceDetailResponse.getBody().getSuccess()){
            throw new BaseException(BasicEnum.IOT_QUERY_DEVICE_ERROR);
        }
        // 根据设备ID查询设备，去数据库查询

        DeviceVo deviceVo = deviceMapper.queryDeviceDetail(deviceDto.getIotId());
        // 合并数据
        // 第一个数据拷贝到第二个数据里面
        BeanUtil.copyProperties( queryDeviceDetailResponse.getBody().getData(),deviceVo, CopyOptions.create().ignoreNullValue());


        return deviceVo;


    }

    @Override
    public QueryDevicePropertyStatusResponseBody.QueryDevicePropertyStatusResponseBodyData queryDevicePropertyStatus(DeviceDto deviceDto) {
        QueryDevicePropertyStatusRequest request = new QueryDevicePropertyStatusRequest();
        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        request.setProductKey(deviceDto.getProductKey());
        request.setDeviceName(deviceDto.getDeviceName());

        QueryDevicePropertyStatusResponse queryDevicePropertyStatusResponse = null;
        try {
            queryDevicePropertyStatusResponse = client.queryDevicePropertyStatus(request);
        } catch (Exception e) {
            throw new BaseException(BasicEnum.IOT_QUERY_DEVICE_PROPERTY_STATUS_ERROR);
        }
        if(!queryDevicePropertyStatusResponse.body.success){
            throw new BaseException(BasicEnum.IOT_QUERY_DEVICE_PROPERTY_STATUS_ERROR);
        }

        return queryDevicePropertyStatusResponse.body.data;
    }

    @Override
    public QueryThingModelPublishedResponseBody.QueryThingModelPublishedResponseBodyData queryThingModelPublished(DeviceDto deviceDto) {
        QueryThingModelPublishedRequest request = new QueryThingModelPublishedRequest();
        request.setProductKey(deviceDto.getProductKey());
        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());

        QueryThingModelPublishedResponse queryThingModelPublishedResponse = null;
        try {
            queryThingModelPublishedResponse = client.queryThingModelPublished(request);
        } catch (Exception e) {
            throw new BaseException(BasicEnum.IOT_QUERY_THING_MODEL_PUBLISHED_ERROR);
        }

        if(!queryThingModelPublishedResponse.body.success){
            throw new BaseException(BasicEnum.IOT_QUERY_THING_MODEL_PUBLISHED_ERROR);
        }

//        HashMap<String, String> map = new HashMap<>();
//        map.put("thingModeIJson",queryThingModelPublishedResponse.body.data.thingModelJson);
//        String s = JSONUtil.toJsonStr(map);
        return queryThingModelPublishedResponse.body.data;

    }

    @Override
    public void updateDevice(DeviceDto deviceDto) {
        // 去数据库查询有没有数据，没有数据就抛出异常
        int count = deviceMapper.queryNickName(deviceDto.getNickname());
        if(count > 0){
            throw new BaseException(BasicEnum.IOT_QUERY_DEVICE_ERROR);
        }

        Device device = BeanUtil.toBean(deviceDto, Device.class);
        device.setHaveEntranceGuard(0);

        // 修改MySQL数据库的内容
        deviceMapper.updateDevice(device);

        // 修改IOT的数据
        BatchUpdateDeviceNicknameRequest.BatchUpdateDeviceNicknameRequestDeviceNicknameInfo nicknameInfo = new BatchUpdateDeviceNicknameRequest.BatchUpdateDeviceNicknameRequestDeviceNicknameInfo();
        nicknameInfo.setDeviceName(deviceDto.getDeviceName());
        nicknameInfo.setProductKey(deviceDto.getProductKey());
        nicknameInfo.setIotId(deviceDto.getIotId());
        nicknameInfo.setNickname(deviceDto.getNickname());

        List<BatchUpdateDeviceNicknameRequest.BatchUpdateDeviceNicknameRequestDeviceNicknameInfo> list =new ArrayList<>();
        list.add(nicknameInfo);
        BatchUpdateDeviceNicknameRequest request = new BatchUpdateDeviceNicknameRequest();
        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        request.setDeviceNicknameInfo(list);
        BatchUpdateDeviceNicknameResponse batchUpdateDeviceNicknameResponse = null;

        try {
            batchUpdateDeviceNicknameResponse = client.batchUpdateDeviceNickname(request);
        } catch (Exception e) {
            throw new BaseException(BasicEnum.IOT_BATCH_UPDATE_DEVICE_ERROR);
        }

        if(!batchUpdateDeviceNicknameResponse.body.success){
            throw new BaseException(BasicEnum.IOT_BATCH_UPDATE_DEVICE_ERROR);
        }

    }

    @Override
    public void deleteDevice(DeviceDto deviceDto) {
        // 删除数据库中的内容
        deviceMapper.deleteDevice(deviceDto.getIotId());

        // 删除IOT中的内容
        DeleteDeviceRequest request = new DeleteDeviceRequest();
        request.setIotId(deviceDto.getIotId());
        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        request.setProductKey(deviceDto.getProductKey());
        DeleteDeviceResponse deleteDeviceResponse = null;
        try {
            deleteDeviceResponse = client.deleteDevice(request);
        } catch (Exception e) {
            throw new BaseException(BasicEnum.IOT_DELETE_DEVICE_ERROR);
        }

        if(!deleteDeviceResponse.body.success){
            throw new BaseException(BasicEnum.IOT_DELETE_DEVICE_ERROR);
        }

    }

    @Override
    public List<DeviceDataGraphVo> queryDeviceDataListByDay(String iotId, Long endTime, String functionId, Long startTime) {
        LocalDateTime start = LocalDateTimeUtil.of(startTime);
        LocalDateTime end = LocalDateTimeUtil.of(endTime);

        List<DeviceDataGraphVo> deviceDataGraphVos = deviceMapper.queryDeviceDataListByDay(start,end,iotId,functionId);
        Map<String, Double> map = deviceDataGraphVos.stream().collect(Collectors.toMap(DeviceDataGraphVo::getDateTime, DeviceDataGraphVo::getDataValue));

        List<DeviceDataGraphVo> list = DeviceDataGraphVo.dayInstance(start);

        list.forEach(item->{
            Double v = map.get(item.getDateTime());
            if(v != null){
                item.setDataValue(v);
            }
        });


        return list;
    }

    @Override
    public List<DeviceDataGraphVo> queryDeviceDataListByWeek(String iotId, Long endTime, String functionId, Long startTime) {
        LocalDateTime start = LocalDateTimeUtil.of(startTime);
        LocalDateTime end = LocalDateTimeUtil.of(endTime);

        List<DeviceDataGraphVo> deviceDataGraphVos = deviceMapper.queryDeviceDataListByWeek(start,end,iotId,functionId);
        Map<String, Double> map = deviceDataGraphVos.stream().collect(Collectors.toMap(DeviceDataGraphVo::getDateTime, DeviceDataGraphVo::getDataValue));

        List<DeviceDataGraphVo> list = DeviceDataGraphVo.weekInstance(start);

        list.forEach(item->{
            Double v = map.get(item.getDateTime());
            if(v != null){
                item.setDataValue(v);
            }
        });


        return list;
    }


}
